package com.boe.common.util;

import cn.hutool.core.util.IdUtil;
import kotlin.text.StringsKt;
import lombok.*;
import com.google.common.base.Strings;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class StringUtil {

    public static <T> T toEnum(String value, Class<T> type) {
        if (Strings.isNullOrEmpty(value)) {
            return null;
        }

        if (type.isEnum() == false) {
            return null;
        }

        var enums = type.getEnumConstants();
        var findOne = Arrays.stream(enums).filter(it -> it.toString().equalsIgnoreCase(value)).findFirst();
        if (findOne.isPresent()) {
            return findOne.get();
        }
        return null;
    }

    public static String getSnowflake() {
        return Long.toString(IdUtil.getSnowflake(RandomUtil.getRandomNumber(1, 31), RandomUtil.getRandomNumber(1, 31)).nextId(), 36);
    }


    public static Boolean hasValue(String value) {
        return !Strings.isNullOrEmpty(value);
    }

    /**
     * 获取第一个有效字符串
     *
     * @param value
     * @return
     */
    public static String asString(Object... value) {
        var ret = Arrays.asList(value)
                .stream()
                .filter(it -> it != null)
                .map(it -> getReadableString(it))
                .filter(it -> !Strings.isNullOrEmpty(it))
                .findFirst();

        if (ret.isPresent()) {
            return ret.get();
        }

        return "";
    }

    public static Integer asInt(Object... value) {
        var ret = Arrays.asList(value)
                .stream()
                .filter(it -> it != null)
                .map(it -> getReadableString(it))
                .filter(it -> !Strings.isNullOrEmpty(it))
                .map(it -> {
                    try {
                        return Integer.parseInt(it);
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(it -> it != null && it != 0)
                .findFirst();

        if (ret.isPresent()) {
            return ret.get();
        }

        return 0;
    }

    private static String getReadableString(Object value) {
        if (value == null) {
            return "";
        }

        if (value instanceof LocalDateTime) {
            if (((LocalDateTime) value).isEqual(LocalDateTime.MIN)) {
                return "";
            }

            return ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }

        if (value instanceof LocalDate) {
            if (((LocalDate) value).isEqual(LocalDate.MIN)) {
                return "";
            }
            return ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }

        if (value instanceof LocalTime) {
            return ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        }

        if (value instanceof Date) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value);
        }


        return value.toString();
    }


    /**
     * 替换字符串,摘抄自 kotlin
     *
     * @param oldValue
     * @param newValue
     * @return
     */
    public static String replaceAll(String value, String oldValue, String newValue, Boolean ignoreCase) {
        return StringsKt.replace(value, oldValue, newValue, ignoreCase);
    }

    public static Boolean allCharIsLowerCase(String value) {
        for (var it :
                value.toCharArray()) {
            if (Character.isLowerCase(it) == false) return false;
        }
        return true;
    }

    public static Boolean allCharIsUpperCase(String value) {
        for (var it : value.toCharArray()) {
            if (Character.isUpperCase(it) == false) return false;
        }
        return true;
    }

    /**
     * 是否全大小，或全小写。 有任意字符则返回false
     */
    public static Boolean allCharIsSameCase(String value) {
        if (value.length() <= 1) return true;
        if (Character.isUpperCase(value.charAt(0))) return allCharIsUpperCase(value);
        if (Character.isLowerCase(value.charAt(0))) return allCharIsLowerCase(value);
        return false;
    }


    /**
     * 分隔为各个部分
     */
    public static List<String> splitWordParts(String value) {
        var ret = Arrays.stream(value.split("[\\W_]+"))
                .map(it -> {
                    if (allCharIsSameCase(it)) {
                        return Arrays.<String>asList(it);
                    } else {
                        //连续大写，按一部分处理
                        var list = Arrays.asList(it.split("(?=[A-Z])"));
                        if (list.size() == 0) return Arrays.<String>asList();
                        //合并连续大写
                        var prevItem = list.get(0);
                        for (var i = 1; i < list.size(); i++) {
                            var item = list.get(i);

                            if (item.length() > 0 && Character.isUpperCase(item.charAt(0)) && allCharIsUpperCase(prevItem)) {
                                prevItem = prevItem + item;
                                list.add(i, prevItem);
                                list.set(i - 1, "");
                            }
                        }

                        return list;
                    }
                }).collect(Collectors.toList());


        return ListUtil.unwindWithList(ret).stream().filter(it2 -> !it2.isEmpty()).collect(Collectors.toList());

    }

    /**
     * 大驼峰 ,仅保留字母，数字
     */

    public static String getBigCamelCase(String value) {

        return String.join("", splitWordParts(value)
                .stream()
                .map(it -> {
                    return Character.toUpperCase(it.charAt(0)) + it.substring(1).toLowerCase();
                })
                .collect(Collectors.toList())
        );
    }

    /**
     * 小驼峰
     */

    public static String getSmallCamelCase(String value) {
        var ret = getBigCamelCase(value);
        if (ret.isEmpty()) return "";
        return Character.toLowerCase(ret.charAt(0)) + ret.substring(1);
    }


    /**
     * 短横线格式，全小写
     */

    public static String getKebabCase(String value) {
        return String.join("-", splitWordParts(value)
                .stream()
                .map(it -> {
                    return it.toLowerCase();
                })
                .collect(Collectors.toList())
        );
    }

    /**
     * 下划线格式，全小写
     */

    public static String getUnderlineCase(String value) {
        return String.join("_", splitWordParts(value)
                .stream()
                .map(it -> {
                    return it.toLowerCase();
                })
                .collect(Collectors.toList())
        );
    }

}
